using MediatR;
using Microsoft.EntityFrameworkCore;
using ProxyServer.Entities;
using ProxyServer.EntityFrameworkCore;
using Yarp.ReverseProxy.Configuration;

namespace ProxyServer.Yarp;

public record ProxyConfigAppliedEvent(AppProxyConfig snapshot) : INotification
{
    public Guid Id { get; set; } = snapshot.SnapshotId;
    public List<RouteConfig> Routes { get; set; } = snapshot.Routes.ToList();

    public List<ClusterConfig> Clusters { get; set; } = snapshot.Clusters.ToList();
    public DateTimeOffset AppliedAt { get; set; } = DateTimeOffset.UtcNow;
}

public sealed class ProxyConfigAppliedEventHandler : INotificationHandler<ProxyConfigAppliedEvent>
{
    private readonly ILogger<ProxyConfigAppliedEventHandler> _logger;
    private readonly IServiceProvider _serviceProvider;

    
    public ProxyConfigAppliedEventHandler(ILogger<ProxyConfigAppliedEventHandler> logger, IServiceProvider serviceProvider)
    {
        _logger = logger;
        _serviceProvider = serviceProvider;
    }

    public async Task Handle(ProxyConfigAppliedEvent notification, CancellationToken cancellationToken)
    {
        _logger.LogInformation("Proxy configuration applied with ID: {Id} at {AppliedAt}", notification.Id, notification.AppliedAt);

        using var scope = _serviceProvider.CreateAsyncScope();
        using var _dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();

        if(await _dbContext.Snapshots.AnyAsync(x => x.Id == notification.Id, cancellationToken))
        {
            _logger.LogWarning("Snapshot with ID {Id} already exists, skipping insertion.", notification.Id);
            return;
        }

        _dbContext.Add(new ProxyConfigSnapshotEntity(notification.Id, notification.Clusters, notification.Routes, notification.AppliedAt));
        await _dbContext.SaveChangesAsync(cancellationToken);
    }
}